package org.oschina.api.user.mail.service;

import java.util.List;
import org.oschina.Config;
import org.oschina.Constants;
import org.oschina.Message;
import org.oschina.Module;
import org.oschina.ResultUtil;
import org.oschina.api.BaseService;
import org.oschina.api.index.service.IndexService;
import org.oschina.api.manage.config.service.ConfigService;
import org.oschina.api.user.mail.UserMailType;
import org.oschina.api.user.mail.dao.UserMailDAO;
import org.oschina.api.user.mail.model.UserMail;
import org.oschina.api.user.mail.vo.UserMailCountVo;
import org.oschina.api.user.mail.vo.UserMailVo;
import org.oschina.api.user.role.service.UserRoleTypeService;
import org.oschina.api.user.user.UserType;
import org.oschina.api.user.user.model.User;
import org.oschina.api.user.user.service.UserService;
import org.oschina.api.user.user.vo.UserVo;
import org.oschina.bean.Pager;
import org.oschina.bean.Result;
import org.oschina.security.annotation.Require;
import org.oschina.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserMailService extends BaseService {

	@Autowired
	private UserMailDAO userMailDAO;
	@Autowired
	private UserMailTypeService userMailTypeService;
	@Autowired
	private UserMailRecordService userMailRecordService;
	@Autowired
	private ConfigService configService;
	@Autowired
	private IndexService indexService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserRoleTypeService userRoleTypeService;
	
	/**
	 * 返回系统邮件
	 * @param pn
	 * @return
	 */
	@Require(authorization=Module.MODULE_47)
	public Pager<UserMailVo> findSystem(int pn)
	{
		Pager<UserMailVo> pager=new Pager(pn,_getCountByType(UserMailType.SYSTEM),_getPageCount(),null);
		if(pager.getData_sum()>0)
			pager.setData(_findByType(UserMailType.SYSTEM, pager.getStart(), pager.getPage_count()));
		return pager;
	}
	
	/**
	 * 删除
	 * @param id
	 * @return
	 */
	@Require
	public Result delete(int id)
	{
		User user=userService.getAuthenticationInfo(getToken());
		UserMailVo userMailVo=_findVoById(id);
		if(userMailVo==null || _isSystem(userMailVo) || !_isTarget(user,userMailVo))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		if(!userMailRecordService.isRead(user.getId(), userMailVo.getId()))
			_updateUnReadCount(user.getId(),userMailVo.getType(),-1);
		
		_delete(userMailVo);
		return ResultUtil.getSuccess(Message.DELETE_SUCCESS);
	}
	
	/**
	 * 设置已读
	 * @param id
	 * @return
	 */
	@Require
	public Result setRead(int id)
	{
		User user=userService.getAuthenticationInfo(getToken());
		UserMailVo userMailVo=_findVoById(id);
		if(userMailVo==null || !_isTarget(user,userMailVo) || userMailRecordService.isRead(user.getId(), userMailVo.getId()))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		userMailRecordService.create(user.getId(), userMailVo.getId());
		_updateUnReadCount(user.getId(),userMailVo.getType(),-1);
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS);
	}
	
	/**
	 * 根据令牌返回未读邮件数量
	 * @return
	 */
	@Require
	public List<UserMailCountVo> getUnReadCount()
	{
		return _getUnReadCount(userService.getAuthenticationInfo(getToken()));
	}
	
	/**
	 * 根据令牌和类型返回
	 * @param type
	 * @param pn
	 * @return
	 */
	@Require
	public Pager<UserMailVo> findByToken(int type,int pn)
	{
		if(userMailTypeService._findVoById(type)==null)
			return null;
		
		User user=userService.getAuthenticationInfo(getToken());
		Pager<UserMailVo> pager=new Pager(pn,_getCountByTargetAndType(user,type),_getPageCount(),null);
		if(pager.getData_sum()>0)
			pager.setData(_findVoByTargetAndRoleAndType(user,type,pager.getStart(),pager.getPage_count()));
		return pager;
	}
	
	/**
	 * 创建邮件
	 * @param token
	 * @param title
	 * @param content
	 * @param target
	 * @return
	 */
	@Require
	public Result create(String title,String content,String target)
	{
		UserVo author=userService.getVo(getToken());
		if(author.getUsername().equals(target))
			return ResultUtil.getFailure(Message.USER_MAIL_CREATE_FAILURE_NOT_YOURSELF);
		
		UserVo targetVo=userService._findVoByUsernameAndType(target,UserType.SIMPLE);
		if(targetVo==null)
			return ResultUtil.getFailure(Message.USER_MAIL_CREATE_FAILURE_TARGET_NOT_FOUND);
		
		return ResultUtil.getSuccess(create(author,targetVo,title,content,UserMailType.SIMPLE));
	}
	
	/**
	 * 创建系统邮件
	 * @param title
	 * @param content
	 * @param role
	 * @return
	 */
	@Require(authorization=Module.MODULE_47)
	public Result createSystem(String title,String content,int role)
	{
		UserVo author=userService.getVo(getToken());
		if(role!=0 && userRoleTypeService.findById(role)==null)
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		return ResultUtil.getSuccess(_create(author,new UserVo(0),title,content,UserMailType.SYSTEM,role));
	}
	
	/**
	 * 删除
	 * @param userMailVo
	 * @return
	 */
	private int _delete(UserMailVo userMailVo)
	{
		return userMailDAO.delete(userMailVo);
	}
	
	/**
	 * 更新未读数量
	 * @param user
	 * @param type
	 * @param count
	 */
	private void _updateUnReadCount(int user,int type,int count)
	{
		userMailDAO.updateUnReadCount(user, type, count);
	}
	
	/**
	 * 根据ID返回
	 * @param id
	 * @return
	 */
	private UserMailVo _findVoById(int id)
	{
		return userMailDAO.findVoById(id);
	}
	
	/**
	 * 根据类型返回
	 * @param type
	 * @param first
	 * @param max
	 * @return
	 */
	private List<UserMailVo> _findByType(int type,int first,int max)
	{
		return userMailDAO.findByType(type, first, max);
	}
	
	/**
	 * 根据类型返回数量
	 * @param type
	 * @return
	 */
	private int _getCountByType(int type)
	{
		return userMailDAO.getCountByType(type);
	}
	
	/**
	 * 创建邮件
	 * @param userMaild
	 * @return
	 */
	private UserMail _create(UserMail userMail,UserVo author,UserVo target)
	{
		userMail.setId(_getIndex());
		userMail.setAuthor(author);
		userMail.setTarget(target);
		userMail.setCreate_time(DateUtil.now());
		return userMailDAO.create(userMail);
	}

	private UserMail _create(UserVo author,UserVo target,String title,String content,int type,int role)
	{
		UserMail userMail=new UserMail();
		userMail.setTitle(title);
		userMail.setContent(content);
		userMail.setType(type);
		userMail.setRole(role);
		return _create(userMail,author,target);
	}
	
	public UserMail create(UserVo author,UserVo target,String title,String content,int type)
	{
		return _create(author,target,title,content,type,0);
	}
	
	/**
	 * 根据用户和权限返回未读邮件数量
	 * @param user
	 * @return
	 */
	private List<UserMailCountVo> _getUnReadCount(User user)
	{
		return userMailDAO.getUnReadCount(user.getId(), user.getRole());
	}
	
	/**
	 * 根据目标和类型还有角色返回
	 * @param user
	 * @param type
	 * @param first
	 * @param max
	 * @return
	 */
	private List<UserMailVo> _findVoByTargetAndRoleAndType(User user,int type,int first,int max)
	{
		return userMailDAO.findVoByTargetAndRoleAndType(user.getId(), user.getRole(), type, first, max);
	}
	
	/**
	 * 根据目标和类型还有角色返回数量
	 * @param user
	 * @param type
	 * @return
	 */
	private int _getCountByTargetAndType(User user,int type)
	{
		return userMailDAO.getCountByTargetAndType(user.getId(), user.getRole(), type);
	}
	
	private int _getPageCount()
	{
		return (Integer) configService.getValueById(Config.CONFIG_20, Integer.class);
	}
	
	private int _getIndex()
	{
		return (Integer)indexService.getMajorById(Constants.INDEX_USER_MAIL);
	}
	
	private boolean _isSimple(UserMailVo userMailVo)
	{
		return userMailVo.getType().equals(UserMailType.SIMPLE);
	}
	
	private boolean _isCall(UserMailVo userMailVo)
	{
		return userMailVo.getType().equals(UserMailType.CALL);
	}
	
	private boolean _isSystem(UserMailVo userMailVo)
	{
		return userMailVo.getType().equals(UserMailType.SYSTEM);
	}
	
	/**
	 * 是否是接收者
	 * @param user
	 * @param userMailVo
	 * @return
	 */
	private boolean _isTarget(User user,UserMailVo userMailVo)
	{
		return ((userMailVo.getTarget().getId().equals(user.getId()) || userMailVo.getTarget().getId().equals(0)) && (userMailVo.getRole().equals(0) || userMailVo.getRole().equals(user.getRole())));
	}
}